package com.yt.server;

import java.io.IOException;
import java.lang.ref.WeakReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import com.yt.server.api.IConnection;
import com.yt.server.api.IContext;
import com.yt.server.api.IGlobalScope;
import com.yt.server.api.IScope;
import com.yt.server.api.action.IActionInvoker;
import com.yt.server.api.comm.ISessionManager;
import com.yt.server.threadpool.ThreadPoolManager;

/**
 * 系统上下文
 * 
 * @author 刘晶
 */
public final class Context implements IContext, ApplicationContextAware {

	public static Logger logger = LoggerFactory.getLogger(Context.class);

	private BeanFactory coreContext = null;

	private static IContext instance = null;

	private static ApplicationContext ctx = null;

	/**
	 * 全局作用域
	 */
	private static IGlobalScope globalScope = null;

	/**
	 * 业务调用者
	 */
	private static IActionInvoker actionInvoker = null;

	/**
	 * 用户管理
	 */
	private static ISessionManager sessionManager = null;

	/**
	 * 线程池处理器
	 */
	private static ThreadPoolManager threadPoolManager = null;

	/**
	 * 当前线程的IConnection
	 */
	private static ThreadLocal<WeakReference<IConnection>> connThreadLocal = new ThreadLocal<WeakReference<IConnection>>();

	public Context() {
		Context.instance = this;
		logger.debug("Context inited...");
		System.out.println("Context inited.");
	}

	public static IContext getInstance() {
		return instance;
	}

	public static IGlobalScope getGlobalScope() {
		return globalScope;
	}

	public static IActionInvoker getActionInvoker() {
		return Context.actionInvoker;
	}

	public static ISessionManager getSessionManager() {
		return Context.sessionManager;
	}

	public static ThreadPoolManager getThreadPoolManager() {
		return Context.threadPoolManager;
	}

	public static ApplicationContext getApplicationContext() {
		return Context.ctx;
	}

	public static IConnection getConnectionLocal() {
		WeakReference<IConnection> ref = connThreadLocal.get();
		if (ref != null) {
			return ref.get();
		} else {
			return null;
		}
	}

	public static void setConnectionLocal(IConnection connection) {
		if (connection != null) {
			connThreadLocal.set(new WeakReference<IConnection>(connection));
			IScope scope = connection.getScope();
			if (scope != null) {
				Thread.currentThread().setContextClassLoader(
						ctx.getClassLoader());
			}
		} else {
			connThreadLocal.remove();
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext arg0)
			throws BeansException {
		ctx = arg0;
		this.coreContext = arg0.getParentBeanFactory();
	}

	@Override
	public Object getBean(String beanId) {
		Object bean = null;
		try {
			bean = ctx.getBean(beanId);
		} catch (NoSuchBeanDefinitionException e) {
			logger.warn("Bean lookup failed for {} in the application context",
					beanId, e);
			e.printStackTrace();
		}
		if (bean == null) {
			bean = getCoreService(beanId);
		}
		return bean;
	}

	@Override
	public boolean hasBean(String beanId) {
		return ctx.containsBean(beanId);
	}

	@Override
	public Object getCoreService(String beanId) {
		return coreContext.getBean(beanId);
	}

	public ClassLoader getClassLoader() {
		return ctx.getClassLoader();
	}

	@Override
	public Resource[] getResources(String arg0) throws IOException {
		return null;
	}

	@Override
	public Resource getResource(String arg0) {
		return null;
	}

	@Override
	public BeanFactory getCoreContext() {
		return coreContext;
	}

	@Override
	public void setCoreContext(BeanFactory coreContext) {
		this.coreContext = coreContext;
	}
	
	@Override
	public void setSessionManager(ISessionManager sessionManager) {
		Context.sessionManager = sessionManager;
	}

	@Override
	public void setActionInvoker(IActionInvoker actionInvoker) {
		Context.actionInvoker = actionInvoker;
	}

	@Override
	public void setGlobalScope(IGlobalScope globalScope) {
		Context.globalScope = globalScope;
	}

	@Override
	public void setThreadPoolManager(ThreadPoolManager threadPoolManager) {
		Context.threadPoolManager = threadPoolManager;
	}
}